import type { RouteLocationNormalized, RouteRecordNormalized } from "vue-router"
import type { App, Plugin } from "vue"

import { unref } from "vue"
import { isObject } from "/@/utils/is"
import { isArray, StringNullableChain } from "lodash"

// 配置外部网址打不开，原因是带了#号，需要替换一下
export const URL_HASH_TAB = `__AGWE4H__HASH__TAG__PWHRG__`

export const noop = () => {}

/**
 * @description:  Set ui mount node
 */
export function getPopupContainer(node?: HTMLElement): HTMLElement {
  return (node?.parentNode as HTMLElement) ?? document.body
}

/**
 * Add the object as a parameter to the URL
 * @param baseUrl url
 * @param obj
 * @returns {string}
 * eg:
 *  let obj = {a: '3', b: '4'}
 *  setObjToUrlParams('www.baidu.com', obj)
 *  ==>www.baidu.com?a=3&b=4
 */
export function setObjToUrlParams(baseUrl: string, obj: any): string {
  let parameters = ""
  for (const key in obj) {
    if (!obj[key] && typeof obj[key] !== "boolean") {
      continue
    }
    parameters += key + "=" + encodeURIComponent(obj[key]) + "&"
  }
  parameters = parameters.replace(/&$/, "")
  return /\?$/.test(baseUrl) ? baseUrl + parameters : baseUrl.replace(/\/?$/, "?") + parameters
}

export function deepMerge<T = any>(src: any = {}, target: any = {}): T {
  let key: string
  for (key in target) {
    src[key] = isObject(src[key]) ? deepMerge(src[key], target[key]) : (src[key] = target[key])
  }
  return src
}

export function openWindow(url: string, opt?: { target?: TargetContext | string; noopener?: boolean; noreferrer?: boolean }) {
  const { target = "__blank", noopener = true, noreferrer = true } = opt || {}
  const feature: string[] = []
  noopener && feature.push("noopener=yes")
  noreferrer && feature.push("noreferrer=yes")
  window.open(url, target, feature.join(","))
}

// dynamic use hook props
export function getDynamicProps<T, U>(props: T): Partial<U> {
  const ret: Recordable = {}

  Object.keys(props).map((key) => {
    ret[key] = unref((props as Recordable)[key])
  })

  return ret as Partial<U>
}

/**
 * 获取表单字段值数据类型
 * @param props
 * @param field
 * @updateBy:zyf
 */
export function getValueType(props, field) {
  const formSchema = unref(unref(props)?.schemas)
  let valueType = "string"
  if (formSchema) {
    const schema = formSchema.filter((item) => item.field === field)[0]
    if (!schema) {
      console.error("schema is null, formSchema: ", formSchema, "field: ", field)
      throw new Error(`schema is null`)
    }
    valueType = schema.valueType
      ? schema.valueType
      : schema.componentProps && schema.componentProps.valueType
        ? schema.componentProps.valueType
        : valueType
  }
  return valueType
}
export function getRawRoute(route: RouteLocationNormalized): RouteLocationNormalized {
  if (!route) return route
  const { matched, ...opt } = route
  return {
    ...opt,
    matched: (matched
      ? matched.map((item) => ({
          meta: item.meta,
          name: item.name,
          path: item.path,
        }))
      : undefined) as RouteRecordNormalized[],
  }
}
/**
 * 深度克隆对象、数组
 * @param obj 被克隆的对象
 * @return 克隆后的对象
 */
export function cloneObject(obj) {
  return JSON.parse(JSON.stringify(obj))
}

export const withInstall = <T>(component: T, alias?: string) => {
  const comp = component as any
  comp.install = (app: App) => {
    app.component(comp.name || comp.displayName, component)
    if (alias) {
      app.config.globalProperties[alias] = component
    }
  }
  return component as T & Plugin
}

export function getPathFromUrl(url: string): string {
  if (!url.startsWith('http')) {
    return url
  }
  try {
    const parsedUrl = new URL(url);
    return parsedUrl.pathname;
  } catch (error) {
    console.error('Invalid URL:', url);
    return '';
  }
}

/**
 * 获取url地址参数
 * @param paramName
 */
export function getUrlParam(paramName, path?: string) {
  return listAllUrlParam(path)[paramName]
}

export function getSubDomain() {
  const href = window.location.href
  const h = href.split(".")[0]
  return h.split("//")[1]
}

/**
 * 移除url中重复的斜杠
 */
export function removeRepeatSlashOfUrl(url) {
  return url.replace(/([^:])(\/\/+)/g, '$1/');
}

/**
 * 获取url中的所有参数
 */
export function listAllUrlParam(path?: string) {
  const res = {}
  const url = path || location.href
  const query = (url.split("?")[1] || "").trim().replace(/^(\?|#|&)/, "")

  if (!query) {
    return res
  }

  query.split("&").forEach((param) => {
    const parts: any = param.replace(/\+/g, " ").split("=")
    const key = decodeURIComponent(parts.shift())
    const val = parts.length > 0 ? decodeURIComponent(parts) : null
    if (res[key] === undefined) {
      res[key] = val
    } else if (Array.isArray(res[key])) {
      res[key].push(val)
    } else {
      res[key] = [res[key], val]
    }
  })
  return res
}

/**
 * 删除url中某个参数,并跳转
 * @param url 路径
 * @param paramNames 参数名
 */
export function deleteUrlParams(url: string, paramNames: string[]) {
  const urlParts = url.split("?")
  const params = new URLSearchParams(urlParts[1])
  paramNames.forEach((key) => params.delete(key))
  return urlParts[0] + "?" + params.toString()
}

/**
 * 休眠（setTimeout的promise版）
 * @param ms 要休眠的时间，单位：毫秒
 * @param fn callback，可空
 * @return Promise
 */
export function sleep(ms: number, fn?: Fn) {
  return new Promise<void>((resolve) =>
    setTimeout(() => {
      fn && fn()
      resolve()
    }, ms)
  )
}

/**
 * 不用正则的方式替换所有值
 * @param text 被替换的字符串
 * @param checker  替换前的内容
 * @param replacer 替换后的内容
 * @returns {String} 替换后的字符串
 */
export function replaceAll(text, checker, replacer) {
  const lastText = text
  text = text.replace(checker, replacer)
  if (lastText !== text) {
    return replaceAll(text, checker, replacer)
  }
  return text
}

/**
 * 获取URL上参数
 * @param url
 */
export function getQueryVariable(url) {
  if (!url) return

  let t,
    n,
    r,
    i = url.split("?")[1],
    s = {}
  ;(t = i.split("&")), (r = null), (n = null)
  for (const o in t) {
    const u = t[o].indexOf("=")
    u !== -1 && ((r = t[o].substr(0, u)), (n = t[o].substr(u + 1)), (s[r] = n))
  }
  return s
}
/**
 * 判断是否显示办理按钮
 * @param bpmStatus
 * @returns {*}
 */
export function showDealBtn(bpmStatus) {
  if (bpmStatus != "1" && bpmStatus != "3" && bpmStatus != "4") {
    return true
  }
  return false
}
/**
 * 数字转大写
 * @param value
 * @returns {*}
 */
export function numToUpper(value) {
  if (value != "") {
    const unit = ["仟", "佰", "拾", "", "仟", "佰", "拾", "", "角", "分"]
    const toDx = (n) => {
      switch (n) {
        case "0":
          return "零"
        case "1":
          return "壹"
        case "2":
          return "贰"
        case "3":
          return "叁"
        case "4":
          return "肆"
        case "5":
          return "伍"
        case "6":
          return "陆"
        case "7":
          return "柒"
        case "8":
          return "捌"
        case "9":
          return "玖"
      }
    }
    const lth = value.toString().length
    value *= 100
    value += ""
    const length = value.length
    if (lth <= 8) {
      let result = ""
      for (let i = 0; i < length; i++) {
        if (i == 2) {
          result = "元" + result
        } else if (i == 6) {
          result = "万" + result
        }
        if (value.charAt(length - i - 1) == 0) {
          if (i != 0 && i != 1) {
            if (result.charAt(0) != "零" && result.charAt(0) != "元" && result.charAt(0) != "万") {
              result = "零" + result
            }
          }
          continue
        }
        result = toDx(value.charAt(length - i - 1)) + unit[unit.length - i - 1] + result
      }
      result += result.charAt(result.length - 1) == "元" ? "整" : ""
      return result
    } else {
      return null
    }
  }
  return null
}

// 解决老的vue2动态导入文件语法 vite不支持的问题
const allModules = import.meta.glob("../views/**/*.vue")
export function importViewsFile(path): Promise<any> {
  if (path.startsWith("/")) {
    path = path.substring(1)
  }
  let page = ""
  if (path.endsWith(".vue")) {
    page = `../views/${path}`
  } else {
    page = `../views/${path}.vue`
  }
  return new Promise((resolve, reject) => {
    let flag = true
    for (const path in allModules) {
      if (path == page) {
        flag = false
        allModules[path]().then((mod) => {
          console.log(path, mod)
          resolve(mod)
        })
      }
    }
    if (flag) {
      reject("该文件不存在:" + page)
    }
  })
}

